The take, takeUntil, takeWhile & takeLast operators allow us to filter out the emitted values from the observable. The take(n) emits the first n values, while takeLast(n) emits the last n values. The takeUntil(notifier) keeps emitting the values until it is notified to stop. takeWhile(predicate) emits the value while values satisfy the predicate. All of the stops emitting once done.
Take operator emits the first n number of values before completing. Any reminder values are ignored.
Syntaxtake(n)
TWhere n is the maximum number of values to emit.
If the source emits more than n values, then take emits only n values and completes
If the source emits less than n number of values, then take emits all of them before completing.
app.component.ts
import { Component, VERSION } from "@angular/core";
import { of } from "rxjs";
import { take } from "rxjs/operators";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
obs = of(1, 2, 3, 4, 5).pipe(take(2));
ngOnInit() {
this.obs.subscribe(val => console.log(val));
}
}
****Console ******
1
2
export class AppComponent {
takeFive = interval(1000).pipe(take(5));
ngOnInit() {
this.takeFive.subscribe(val => console.log(val));
}
}
****Console ******
0
1
2
3
4
The takeUntil operator returns an Observable that emits value from the source Observable until the notifier Observable emits a value.
Syntax
TakeUntil(notifier: Observable): Observable
We must pass a notifier observable as the argument to the TakeUntil Operator
TakeUntil emits the values from the Source Observable as long as it does not receive any value from the notifier observable
When the notifier emits a value, the TakeUntil completes the Source observable.
If the notifier completes without emitting any value, then the TakeUntil keeps emitting values from the source and completes when the source completes.
ExampleIn the example below, we create a notifier observable
notifier= new Subject();
The notifier observable emits a value , when use clicks on the stop button.
stopObs() {
this.notifier.next();
this.notifier.complete();
}
Use the takeUntil in the source observable as shown below
obs = interval(1000).pipe(takeUntil(this.notifier));
Run the app. The source observable stops when you click on stop button.
app.component.ts
import { Component, VERSION } from "@angular/core";
import { of, interval, Subject, Observable } from "rxjs";
import { take, takeUntil, tap } from "rxjs/operators";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
notifier = new Subject();
obs = interval(1000).pipe(takeUntil(this.notifier));
ngOnInit() {
this.obs.subscribe(val => console.log(val));
}
stopObs() {
this.notifier.next();
this.notifier.complete();
}
}
<h1>TakeUntil Example</h1>
<button (click)="stopObs()">Stop</button>
<br>
One of the use cases of takeUntil is to automatically unsubscribe all the observables. You can refer to it from the tutorial on Unsubscribing from an observable.
TakeWhile operator will keep emitting the value from the source observable as long as they pass the given condition (predicate). When it receives a value that does not satisfy the condition it completes the observable. No further values are emitted even if they satisfy the condition.
takeWhile(predicate: function(value, index): boolean,
inclusive?: boolean): Observable
Where predicate is the condition
If inclusive is true, then the emits the value, which does not pass the condition before terminating the observable.
ExampleIn the code below takeWhile tests the condition val < 3 against the incoming values. When it receives the value 3, which does not satisfy the condition, the observable completes. It does not emit any further values although the stream still has values that satisfy the condition.
import { Component, VERSION } from "@angular/core";
import { of, interval, Subject, Observable } from "rxjs";
import { take, takeUntil, takeWhile, tap } from "rxjs/operators";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3)
.pipe(
takeWhile(val => val < 3)
);
ngOnInit() {
this.obs.subscribe(val => console.log(val));
}
}
*** Console ***
1
2
With inclusive is set to true, takewhile also emits the value 3 before completing the observable.
export class AppComponent {
obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3)
.pipe(
takeWhile(val => val < 3, true)
);
ngOnInit() {
this.obs.subscribe(val => console.log(val));
}
}
*** Console ***
1
2
3
evenNumbers = of(2, 4, 6, 3, 8)
.pipe(takeWhile(n => n % 2 == 0))
.subscribe(val => console.log(val));
**Console ***
2
4
6
//8 is not emitted
Both takeWhile & filter uses the condition to filter out the incoming stream. Both allows only the matching values to pass through discarding the others.
The difference is that takeWhile discards the rest of the stream, when it receives the first value that does not satisfy the condition (If the inclusive is set to true, then it also emits the last value even when it does not satisfy the condition). The filter operator never stops the observable.
The following example, filter operator does not stop when it receives the value 3. But it discards it and continues further until the stream itself completes.
Example
obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3)
.pipe(
filter(val => val < 3, true)
);
ngOnInit() {
this.obs.subscribe(val => console.log(val));
}
***Console ****
1
2
1
2
1
2
TakeLast operator emits the last n number of values from the source observable.
Syntax
takeLast<T>(n: number)
Where n is the maximum number of values to emit.
To know the last n number of values, the TakeLast needs to wait for the source to complete. Hence if the source never completes, then TakeLast will never emit a value.
When the stream completes, the takeLast will
import { Component, VERSION } from "@angular/core";
import { of, range, Observable } from "rxjs";
import { takeLast } from "rxjs/operators";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
obs = range(1, 100).pipe(takeLast(3));
ngOnInit() {
this.obs.subscribe(val => console.log(val));
}
}
***Console****
98
99
100